home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 November: Tool Chest / Dev.CD Nov 96 TC / Dev.CD Nov 96 TC.toast / Tool Chest / Development Tools & Languages / HyperCard Related / APDA HyperCard Toolkits / HyperCard Video Toolkit 2.0 / HVT #2 / Advanced Material / Video Sources / vidDrvrP6000A.p < prev    next >
Encoding:
Text File  |  1995-02-07  |  17.8 KB  |  637 lines  |  [TEXT/MPS ]

  1. (*
  2.     vidDrvrP6000A(cmd,parameters) -- Driver for the Pioneer 6000A & 6010A videodisc player. The cmd parameter specifies the
  3.         function to be performed (p1 is the first parameter after cmd; p2 is the second, etc.):
  4.  
  5.                     Command        Function
  6.                     ---------        --------
  7.                     chapter            Return the chapter currently being displayed.
  8.                     control            Execute a series of control functions. Each addition parameter is a keyword to be
  9.                                         executed. If the keyword doesn't make sense here, pass it on to configureSPort.
  10.                                         The following keywords are understood by the video driver:
  11.                                                     Keyword                        Function
  12.                                                     --------                        --------
  13.                                                     init or reset                    Reset the player, configure the serial port (the baud rate is set to
  14.                                                                                         the highest available for the selected player).
  15.                                                     eject or reject                Eject the disc from the player.
  16.                                                     audioOff                        Turn off both audio channels.
  17.                                                     audio1On                        Turn on audio channel 1.
  18.                                                     audio2On                        Turn on audio channel 2.
  19.                                                     stereoOn                        Turn on both audio channels.
  20.                                                     pictureOn/pictureOff    Turn on/off the picture.
  21.                                                     framesOn/framesOff    Turn on/off the display of frame numbers.
  22.                                                     frameMode                    Set player to frame number mode.
  23.                                                     chapterMode                    Set player to chapter number mode.
  24.                                                     timeMode                        Set player to time mode.
  25.                                                     defaultComm                    Set default communications settings for this player.
  26.                     extended        Execute a function specific to the player. This player doesn't have any (yet).
  27.                     fps                Set the frames per second for the next playVideo command to p1, which can be a number or
  28.                                         one of "slowest", "slower", "slow", "normal", "fast", "faster", "fastest".
  29.                     frame            Return the current frame number.
  30.                     name            Return the long name of the player.
  31.                     play                Start a sequence playing, from p1 to p2, which are frame numbers, chapter numbers, or times,
  32.                                         depending upon the mode.
  33.                     scan                Scan forward or backward, depending upong whether p1 is "forward" or "backward".
  34.                     search            Search to frame, chapter, or time p1.
  35.                     sendCmd        Send command p1 to the player and wait for an acknowlege.
  36.                     speeds            Return the frames per second speeds allowed with this player.
  37.                     status            Return the status of the play, which is a comma-separated list containing:
  38.                                                         Keyword                                            Meaning
  39.                                                         --------                                            --------
  40.                                                         doorOpen or park or still or play        State of player.
  41.                                                         CLV or CAV                                        Type of disc.
  42.                                                         disc12inch or disc8inch                        Size of disc being played.
  43.                                                         side1 or side2                                    Side of disc being played.
  44.                     step                Step p1 frames forward (or backward if it's negative), and do it p2 times.
  45.                     time                Return the time of the frame currently being displayed, in 1/60ths of a second since the start
  46.                                         of the disc.
  47.                     version            Return the version of this player driver.
  48.  
  49.     To compile and link this file using Macintosh Programmer's Workshop,
  50.  
  51.         pascal -w vidDrvrP6000A.p
  52.         link -m ENTRYPOINT -o HyperCommands -rt XFCN=8031 -sn Main=vidDrvrP6000A ∂
  53.             vidDrvrP6000A.p.o "{MPW}"Libraries:interface.o "{MPW}"PLibraries:PasLib.o
  54.  
  55.     Copyright © 1988 Apple Computer, Inc.
  56.  
  57.     2/88 - Initial coding by Harry R. Chesley.
  58. *)
  59.  
  60. {$R-}
  61.  
  62. {$S vidDrvrP6000A }     { Segment name must be the same as the command name. }
  63.  
  64. unit DummyUnit;
  65.  
  66. interface
  67.  
  68. uses MemTypes, QuickDraw, OSIntf, ToolIntf, HyperXCmd;
  69.  
  70. procedure EntryPoint(paramPtr: XCmdPtr);
  71.     
  72. implementation
  73.  
  74. type
  75.  
  76. Str31 = String[31];
  77.  
  78. procedure vidDrvrP6000A(paramPtr: XCmdPtr); forward;
  79.  
  80. procedure EntryPoint(paramPtr: XCmdPtr);
  81.  
  82.     begin
  83.         vidDrvrP6000A(paramPtr);
  84.     end;
  85.  
  86. procedure vidDrvrP6000A(paramPtr: XCmdPtr);
  87.  
  88.     var returnValue: str255;
  89.         pCount: integer;
  90.         p1, p2: str255;
  91.         str: str255;
  92.         i: integer;
  93.         inChapterMode: boolean;
  94.  
  95.     {$I XCmdGlue.inc}
  96.  
  97.     procedure Fail(errMsg: Str255); { set theResult and quit }
  98.         begin
  99.             paramPtr^.returnValue := PasToZero(errMsg);
  100.             exit(vidDrvrP6000A);
  101.         end;
  102.  
  103.     {$I VideoUtil.inc}
  104.  
  105.     procedure sendCmd(theCommand: str255);
  106.         { Send a command to the player. Note that this player driver, unlike most, does not
  107.             wait for a positive ack after sending a command. }
  108.  
  109.         var i: integer;
  110.             theChar: char;
  111.             doingDigits: boolean;
  112.             str: str255;
  113.  
  114.         begin
  115.             SendCardMessage('sendSPort "@"');
  116.             doingDigits := false;
  117.             for i := 1 to length(theCommand) do
  118.                 begin
  119.                     theChar := theCommand[i];
  120.                     if doingDigits then
  121.                         begin
  122.                             if (theChar >= '0') and (theChar <= '9') then
  123.                                 begin
  124.                                     case theChar of
  125.                                         '0': str := '3';
  126.                                         '1': str := '0';
  127.                                         '2': str := '8';
  128.                                         '3': str := '4';
  129.                                         '4': str := '2';
  130.                                         '5': str := 'A';
  131.                                         '6': str := '6';
  132.                                         '7': str := '1';
  133.                                         '8': str := '9';
  134.                                         '9': str := '5';
  135.                                         end;
  136.                                     SendCardMessage(Concat('sendSPort "',str,'F"'));
  137.                                 end
  138.                             else doingDigits := false;
  139.                         end
  140.                     else
  141.                         begin
  142.                             if theChar = '.' then doingDigits := true
  143.                             else SendCardMessage(Concat('sendSPort "',Copy(theCommand,i,1),'"'));
  144.                         end;
  145.                 end;
  146.         end;
  147.  
  148.     function chapter: str255;
  149.         { Return the current chapter. }
  150.  
  151.         var str: str255;
  152.             endTick: longInt;
  153.             charCount: longInt;
  154.  
  155.         begin
  156.             { Ask for the chapter number in binary. }
  157.             sendCmd('E7D2');
  158.             { Get it or time out. }
  159.             endTick := TickCount+120;
  160.             repeat charCount := StrToLong(Evalstr('charsAvailable()'));
  161.             until (charCount >= 1) or (TickCount > endTick);
  162.             { If we got something... }
  163.             chapter := 'noAnswer';
  164.             if charCount >= 1 then
  165.                 begin
  166.                     { Compute chapter number. }
  167.                     str := EvalStr('recvChars(1)');
  168.                     if length(str) <> 0 then chapter := LongToStr(ord(str[1]))
  169.                     else chapter := '0';
  170.                 end;
  171.         end;
  172.  
  173.     function status: str255;
  174.         { Return the current status. }
  175.  
  176.         var str, str2: str255;
  177.             endTick: longInt;
  178.             charCount: longInt;
  179.             theResult: str255;
  180.  
  181.         begin
  182.             { Clear out any pending input. }
  183.             EvalAndDispose('recvUpTo(empty,0,empty)');
  184.     
  185.             { Ask for the status in binary. }
  186.             sendCmd('E7D5');
  187.             { Get it or time out. }
  188.             endTick := TickCount+120;
  189.             repeat charCount := StrToLong(Evalstr('charsAvailable()'));
  190.             until (charCount >= 3) or (TickCount > endTick);
  191.             { If we got something... }
  192.             if charCount >= 3 then
  193.                 begin
  194.                     { str := character one. }
  195.                     str := EvalStr('recvChars(1)');
  196.                     if length(str) = 0 then
  197.                         begin
  198.                             str[0] := chr(1); str[1] := chr(0);
  199.                         end;
  200.                     { str2 := character two. }
  201.                     str2 := EvalStr('recvChars(1)');
  202.                     if length(str2) = 0 then
  203.                         begin
  204.                             str2[0] := chr(1); str2[1] := chr(0);
  205.                         end;
  206.                     { Dump char three. }
  207.                     EvalAndDispose('recvChars(1)');
  208.                     { Compute the status. }
  209.                     if (ord(str[1]) mod 128) in [104,120,136] then theResult := 'park'
  210.                     else if (ord(str[1]) mod 4) = 1 then theResult := 'still'
  211.                     else theResult := 'play';
  212.                     if (ord(str2[1]) mod 2) = 1 then theResult := Concat(theResult,',CLV')
  213.                     else theResult := Concat(theResult,',CAV');
  214.  
  215.                     { Now get the other status info. }
  216.                     EvalAndDispose('recvUpTo(empty,0,empty)');
  217.             
  218.                     { Ask for the status in binary. }
  219.                     sendCmd('E791');
  220.                     { Get it or time out. }
  221.                     endTick := TickCount+120;
  222.                     repeat charCount := StrToLong(Evalstr('charsAvailable()'));
  223.                     until (charCount >= 2) or (TickCount > endTick);
  224.                     { If we got something... }
  225.                     if charCount >= 2 then
  226.                         begin
  227.                             { str := character one. }
  228.                             str := EvalStr('recvChars(1)');
  229.                             str := EvalStr('recvChars(1)');
  230.                             if length(str) = 0 then
  231.                                 begin
  232.                                     str[0] := chr(1); str[1] := chr(0);
  233.                                 end;
  234.                             { Compute the status. }
  235.                             if BitAnd(ord(str[1]),$00080) <> 0 then theResult := Concat(theResult,',disc8inch')
  236.                             else theResult := Concat(theResult,',disc12inch');
  237.                             if BitAnd(ord(str[1]),$00040) <> 0 then theResult := Concat(theResult,',side2')
  238.                             else theResult := Concat(theResult,',side1');
  239.                         end;
  240.                     status := theResult;
  241.                 end
  242.             else status := 'noAnswer';
  243.         end;
  244.  
  245.     procedure search(var toFrame: str255; blankSearch: boolean);
  246.         { Search to the specified frame, using blanking if blankSearch is true. }
  247.  
  248.         begin
  249.             if blankSearch then sendCmd('1C');
  250.             sendCmd(Concat('.',toFrame,'.F7'));
  251.             while StringEqual(Copy(status,1,4),'play') do ;
  252.             if blankSearch then sendCmd('1B');
  253.         end;
  254.  
  255.     procedure stop;
  256.         { Stop the player. }
  257.  
  258.         begin
  259.             sendCmd('FB');
  260.         end;
  261.  
  262.     procedure control(var keywd: str255);
  263.         { Handle a control command. }
  264.  
  265.         type
  266.             audioModes = (off,oneOn,twoOn,stereo);
  267.  
  268.         var numberOfParms: integer;
  269.             i: integer;
  270.             parm: str255;
  271.  
  272.         procedure ejectPlayer;
  273.             { Eject the disc. }
  274.     
  275.             begin
  276.                 { Send the appropriate eject command. }
  277.                 sendCmd('F9');
  278.             end;
  279.     
  280.         procedure audio(onOff: audioModes);
  281.             { Set the audio mode. }
  282.     
  283.             begin
  284.                 { Send the appropriate audio channel command. }
  285.                 case onOff of
  286.                     off:
  287.                         begin
  288.                             sendCmd('AA');
  289.                             sendCmd('A5');
  290.                         end;
  291.                     oneOn:
  292.                         begin
  293.                             sendCmd('AB');
  294.                             sendCmd('A5');
  295.                         end;
  296.                     twoOn:
  297.                         begin
  298.                             sendCmd('AA');
  299.                             sendCmd('A7');
  300.                         end;
  301.                     stereo:
  302.                         begin
  303.                             sendCmd('AB');
  304.                             sendCmd('A7');
  305.                         end;
  306.                     end;
  307.             end;
  308.         
  309.         procedure picture(onOff: boolean);
  310.             { Turn the picture on or off. }
  311.     
  312.             begin
  313.                 { Send the appropriate picture command. }
  314.                 if onOff then sendCmd('1B')
  315.                 else sendCmd('1C');
  316.             end;
  317.     
  318.         procedure frames(onOff: boolean);
  319.             { Turn the frame display on or off. }
  320.     
  321.             begin
  322.                 { Send the appropriate frame display command. }
  323.                 if onOff then sendCmd('E00FF1')
  324.                 else sendCmd('E13FF1');
  325.             end;
  326.     
  327.         procedure defaultComm;
  328.             { Set the default communications settings. }
  329.  
  330.             begin
  331.                 { Set the port configuration. }
  332.                 SendCardMessage('configureSPort baud9600,echoOff,editOff,linefeedOff,stripOff');
  333.             end;
  334.  
  335.         procedure setMode(theMode: str255);
  336.             { Set the frame/chapter/time mode. }
  337.     
  338.             begin
  339.                 SetStrGlobal('videoMode',theMode);
  340.                 if StringEqual(theMode,'chapterMode') then sendCmd('8C')
  341.                 else if StringEqual(theMode,'timeMode') then sendCmd('8D')
  342.                 else sendCmd('8E')
  343.             end;
  344.     
  345.         procedure initPlayer;
  346.             { Initialize the player. }
  347.     
  348.             var str: str255;
  349.                 endTick: longInt;
  350.     
  351.             begin
  352.                 { Empty out the globals. }
  353.                 SetStrGlobal('videoMode','');
  354.                 SetStrGlobal('blankNextVideo','');
  355.                 SetStrGlobal('videoSpeed','');
  356.     
  357.                 { Send the reset command for this player. }
  358.                 sendCmd('FD');
  359.  
  360.                 { Wait for it to spin up. }
  361.                 endTick := TickCount+3600;
  362.                 repeat
  363.                     sendCmd('E4D4');
  364.                     str := EvalStr('recvUpTo(empty,20,empty)');
  365.                     if length(str) >= 2 then
  366.                         if str[2] = '4' then leave;
  367.                 until TickCount > endTick;
  368.  
  369.                 { Force it to stop. }
  370.                 sendCmd('BF');
  371.                 stop;
  372.  
  373.                 { Reset the player to known defaults. }
  374.                 setMode('');
  375.                 audio(stereo);
  376.                 frames(false);
  377.                 picture(true);
  378.             end;
  379.     
  380.         begin
  381.             if StringEqual(keywd,'init') or StringEqual(keywd,'reset') then initPlayer
  382.             else if StringEqual(keywd,'eject') or StringEqual(keywd,'reject') then ejectPlayer
  383.             else if StringEqual(keywd,'audioOff') then audio(off)
  384.             else if StringEqual(keywd,'audio1On') then audio(oneOn)
  385.             else if StringEqual(keywd,'audio2On') then audio(twoOn)
  386.             else if StringEqual(keywd,'stereoOn') then audio(stereo)
  387.             else if StringEqual(keywd,'pictureOn') then picture(true)
  388.             else if StringEqual(keywd,'pictureOff') then picture(false)
  389.             else if StringEqual(keywd,'framesOn') then frames(true)
  390.             else if StringEqual(keywd,'framesOff') then frames(false)
  391.             else if StringEqual(keywd,'defaultComm') then defaultComm
  392.             else if StringEqual(keywd,'frameMode') then setMode('')
  393.             else if StringEqual(keywd,'chapterMode') then setMode('chapterMode')
  394.             else if StringEqual(keywd,'timeMode') then setMode('timeMode')
  395.             else SendCardMessage(Concat('configureSPort ',keywd));
  396.         end;
  397.  
  398.     function extended(var keywd: str255): str255;
  399.         { Execute an extended function or command. }
  400.  
  401.         begin
  402.             { No extended command for this player. }
  403.         end;
  404.  
  405.     procedure fps(var fpsKeywd: str255);
  406.         { Set the frame per second. }
  407.  
  408.         var speed: str255;
  409.  
  410.         begin
  411.             speed := '';
  412.  
  413.             { Default speed settings are fine, except: }
  414.             if StringEqual(fpsKeywd,'fastest') then speed := '90';
  415.  
  416.             { Set it. }
  417.             if speed <> '' then SetStrGlobal('videoSpeed',speed);
  418.         end;
  419.  
  420.     function frame: str255;
  421.         { Return the current frame number. }
  422.  
  423.         var str, str2: str255;
  424.             endTick: longInt;
  425.             charCount: longInt;
  426.  
  427.         begin
  428.             { Ask for the frame number in binary. }
  429.             sendCmd('E7D3');
  430.             { Get it or time out. }
  431.             endTick := TickCount+120;
  432.             repeat charCount := StrToLong(Evalstr('charsAvailable()'));
  433.             until (charCount >= 2) or (TickCount > endTick);
  434.             { If we got something... }
  435.             if charCount >= 2 then
  436.                 begin
  437.                     { str := character one. }
  438.                     str := EvalStr('recvChars(1)');
  439.                     if length(str) = 0 then
  440.                         begin
  441.                             str[0] := chr(1); str[1] := chr(0);
  442.                         end;
  443.                     { str2 := character two. }
  444.                     str2 := EvalStr('recvChars(1)');
  445.                     if length(str2) = 0 then
  446.                         begin
  447.                             str2[0] := chr(1); str2[1] := chr(0);
  448.                         end;
  449.                     { Compute the frame number. }
  450.                     frame := LongToStr(BitOr(BitShift(ord(str[1]),8),ord(str2[1])))
  451.                 end
  452.             else frame := 'noAnswer';
  453.         end;
  454.  
  455.     function name: str255;
  456.         { Return the long name of the player. }
  457.  
  458.         begin
  459.             name := 'Pioneer 6000A,Pioneer 6010A';
  460.         end;
  461.  
  462.     procedure play(var firstFrame,lastFrame,speed: str255; blankSearch, chapterMode: boolean);
  463.         { Play a segment. }
  464.  
  465.         var lastFrameNum: longInt;
  466.             startHere: boolean;
  467.             playToLast: boolean;
  468.             fpsNum: longInt;
  469.             rev: boolean;
  470.  
  471.         begin
  472.             { Figure out if we're playing to special (non-numeric markers). }
  473.             startHere := StringEqual(firstFrame,'here');
  474.             playToLast := StringEqual(lastFrame,'lastFrame');
  475.             if playToLast then
  476.                 begin
  477.                     if chapterMode then
  478.                         begin
  479.                             lastFrame := '99';
  480.                             lastFrameNum := 99;
  481.                         end
  482.                     else
  483.                         begin
  484.                             lastFrame := '54000';
  485.                             lastFrameNum := 54000;
  486.                         end;
  487.                 end
  488.             else lastFrameNum := StrToLong(lastFrame);
  489.             { Set the speed. }
  490.             fpsNum := StrToLong(speed);
  491.             if fpsNum = 0 then fpsNum := 30;
  492.  
  493.             { Figure out whether we're playing forward or reverse. }
  494.             rev := (not playToLast) and
  495.                         (((not startHere) and (lastFrameNum < StrToLong(firstFrame))) or (lastFrameNum = 0));
  496.  
  497.             { Adjust ending point if we're playing backward in chapter mode (since it stops as soon as it enters the chapter). }
  498.             if rev and chapterMode and (lastFrameNum <> 0) then
  499.                 begin
  500.                     lastFrameNum := lastFrameNum-1;
  501.                     lastFrame := LongToStr(lastFrameNum);
  502.                 end;
  503.  
  504.             { Go to the first frame. }
  505.             if not startHere then search(firstFrame,blankSearch);
  506.             if fpsNum < 30 then sendCmd(Concat('.',LongToStr(30 div fpsNum),'.ED'))
  507.             else if fpsNum > 30 then sendCmd(Concat('.',LongToStr(fpsNum div 30),'.EC'))
  508.             else sendCmd('.1.ED');
  509.             { Play it. }
  510.             if rev then
  511.                 begin
  512.                     if lastFrameNum = 0 then sendCmd('FA')
  513.                     else sendCmd(Concat('.',lastFrame,'.FA'));
  514.                 end
  515.             else
  516.                 begin
  517.                     if fpsNum = 30 then
  518.                         begin
  519.                             if (lastFrameNum <> 0) and (not playToLast) then sendCmd(Concat('.',lastFrame,'.F3'))
  520.                             else sendCmd('FD');
  521.                         end
  522.                     else if playToLast then sendCmd('F2')
  523.                     else sendCmd(Concat('.',lastFrame,'.F2'));
  524.                 end;
  525.         end;
  526.  
  527.     function scan(scanForward, chapterMode: boolean): str255;
  528.         { Scan forward (if scanForward is true), or backward. }
  529.  
  530.         begin
  531.             if scanForward then
  532.                 begin
  533.                     if chapterMode then sendCmd('.99.83')
  534.                     else sendCmd('.54000.83')
  535.                 end
  536.             else sendCmd('.0.83');
  537.             scan := 'only once';
  538.         end;
  539.  
  540.     procedure step(goForward: boolean);
  541.         { Step one frame forward (if goForward is true) or backward. }
  542.  
  543.         begin
  544.             if goForward then SendCmd('F6')
  545.             else SendCmd('FE');
  546.         end;
  547.  
  548.     function speeds: str255;
  549.         { Return the valid speeds for this player. }
  550.  
  551.         begin
  552.             speeds := '1,2,3,5,6,10,15,20,30,60,90';
  553.         end;
  554.  
  555.     function time: str255;
  556.         { Return the time for the current frame. }
  557.  
  558.         begin
  559.             time := 'notImplemented';
  560.         end;
  561.  
  562.     function version: str255;
  563.         { Return the version for this player driver. }
  564.  
  565.         begin
  566.             version := 'P6000A 1.0';
  567.         end;
  568.  
  569.     begin
  570.         pCount := paramPtr^.paramCount;
  571.  
  572.         if pCount <= 0 then Fail('parameter count is not > 0');
  573.  
  574.         if pCount > 1 then GetStrParm(2,p1)
  575.         else p1 := '';
  576.         if pCount > 2 then GetStrParm(3,p2)
  577.         else p2 := '';
  578.  
  579.         GetStrParm(1,str);
  580.  
  581.         returnValue := '';
  582.  
  583.         if StringEqual(str,'chapter') then returnValue := chapter
  584.         else if StringEqual(str,'control') then
  585.             begin
  586.                 for i := 2 to pCount do
  587.                     begin
  588.                         GetStrParm(i,str);
  589.                         control(str);
  590.                     end;
  591.             end
  592.         else if StringEqual(str,'extended') then returnValue := extended(p1)
  593.         else if StringEqual(str,'fps') then fps(p1)
  594.         else if StringEqual(str,'frame') then returnValue := frame
  595.         else if StringEqual(str,'name') then returnValue := name
  596.         else if StringEqual(str,'play') then
  597.             begin
  598.                 GetStrGlobal('videoMode',str);
  599.                 inChapterMode := StringEqual(str,'chapterMode');
  600.                 GetStrGlobal('blankNextVideo',str);
  601.                 if str = '' then
  602.                     begin
  603.                         GetStrGlobal('videoSpeed',str);
  604.                         play(p1,p2,str,false,inChapterMode);
  605.                     end
  606.                 else
  607.                     begin
  608.                         GetStrGlobal('videoSpeed',str);
  609.                         play(p1,p2,str,true,inChapterMode);
  610.                     end;
  611.             end
  612.         else if StringEqual(str,'scan') then
  613.             begin
  614.                 GetStrGlobal('videoMode',str);
  615.                 inChapterMode := StringEqual(str,'chapterMode');
  616.                 if length(p1) < 1 then returnValue := scan(true,inChapterMode)
  617.                 else returnValue := scan(not ((p1[1] = 'b') or (p1[1] = 'B')),inChapterMode);
  618.             end
  619.         else if StringEqual(str,'search') then
  620.             begin
  621.                 GetStrGlobal('blankNextVideo',str);
  622.                 search(p1,str <> '');
  623.             end
  624.         else if StringEqual(str,'sendCmd') then sendCmd(p1)
  625.         else if StringEqual(str,'step') then step(p1 = '1')
  626.         else if StringEqual(str,'speeds') then returnValue := speeds
  627.         else if StringEqual(str,'status') then returnValue := status
  628.         else if StringEqual(str,'stop') then stop
  629.         else if StringEqual(str,'time') then returnValue := time
  630.         else if StringEqual(str,'version') then returnValue := version;
  631.  
  632.         { Return the result (if any). }
  633.         paramPtr^.returnValue := PasToZero(returnValue)
  634.     end;
  635.  
  636. end.
  637.